#pragma once
// arraytp.h -- Array Template
//#ifndef ARRAYTP_H_
//#define ARRAYTP_H_
//
//#include <iostream>
//#include <cstdlib>
//
//template <class T, int n>
//class ArrayTP
//{
//private:
//	T ar[n];
//public:
//	ArrayTP() {};
//	explicit ArrayTP(const T& v);
//	virtual T& operator[](int i);
//	virtual T operator[](int i) const;
//};
//
//template <class T, int n>
//ArrayTP<T, n>::ArrayTP(const T& v)
//{
//	for (int i = 0; i < n; i++)
//	{
//		ar[i] = v;
//	}
//}
//
//template <class T, int n>
//T& ArrayTP<T, n>::operator[](int i)
//{
//	if (i < 0 || i >= n)
//	{
//		std::cerr << "Error in array limits: " << i
//			<< " is out of range\n";
//		std::exit(EXIT_FAILURE);
//	}
//	return ar[i];
//}
//
//template <class T, int n>
//T ArrayTP<T, n>::operator[](int i) const
//{
//	if (i < 0 || i >= n)
//	{
//		std::cerr << "Error in array limits: " << i
//			<< " is out of range\n";
//		std::exit(EXIT_FAILURE);
//	}
//	return ar[i];
//}
//#endif // !ARRAYTP_H_

// stacktp.h -- a stack template
//#ifndef STACKTP_H_
//#define STACKTP_H_
//
//template <class Type>
//class Stack
//{
//private:
//	enum { MAX = 10 };	// constant specific to class
//	Type items[MAX];	// holds stack items
//	int top;			// index for top stack item
//public:
//	Stack();
//	bool isempty();
//	bool isfull();
//	bool push(const Type& item);	// add item to stack
//	bool pop(Type& item);			// pop top into item
//};
//
//template <class Type>
//Stack<Type>::Stack()
//{
//	top = 0;
//}
//
//template <class Type>
//bool Stack<Type>::isempty()
//{
//	return top == 0;
//}
//
//template <class Type>
//bool Stack<Type>::isfull()
//{
//	return top == MAX;
//}
//
//template <class Type>
//bool Stack<Type>::push(const Type& item)
//{
//	if (top < MAX)
//	{
//		items[top++] = item;
//		return true;
//	}
//	else
//	{
//		return false;
//	}
//}
//
//template <class Type>
//bool Stack<Type>::pop(Type& item)
//{
//	if (top > 0)
//	{
//		item = items[--top];
//		return true;
//	}
//	else
//	{
//		return false;
//	}
//}
//#endif // !STACKTP_H_

// tv.h -- Tv and Remote classes
//#ifndef TV_H_
//#define TV_H_
//
//class Tv
//{
//public:
//	friend class Remote;	// Remote can access Tv private parts
//	enum { Off, On };
//	enum { MinVal, MaxVal = 20 };
//	enum { Antenna, Cable };
//	enum { TV, DVD };
//
//	Tv(int s = Off, int mc = 125) :state(s), volume(5),
//		maxchannel(mc), channel(2), mode(Cable), input(TV) {}
//	void onoff() { state = (state == On) ? Off : On; }
//	bool ison() const { return state == On; }
//	bool volup();
//	bool voldown();
//	void chanup();
//	void chandown();
//	void set_mode() { mode = (mode == Antenna) ? Cable : Antenna; }
//	void set_input() { input = (input == TV) ? DVD : TV; }
//	void settings() const;	// display all settings
//
//private:
//	int state;		// on or off
//	int volume;		// assumed to be digitized
//	int maxchannel;	// maximum number of channels
//	int channel;	// current channel setting
//	int mode;		// broadcase or cable
//	int input;		// TV or DVD
//};
//
//class Remote
//{
//private:
//	int mode;	// controls TV or DVD
//public:
//	Remote(int m = Tv::TV) :mode(m) {}
//	bool volup(Tv& t) { return t.volup(); }
//	bool voldown(Tv& t) { return t.voldown(); }
//	void onff(Tv& t) { t.onoff(); }
//	void chanup(Tv& t) { t.chanup(); }
//	void chandown(Tv& t) { t.chandown(); }
//	void set_chan(Tv& t, int c) { t.channel = c; }
//	void set_mode(Tv& t) { t.set_mode(); }
//	void set_input(Tv& t) { t.set_input(); }
//};
//#endif // !TV_H_

// tvfm.h -- Tv and Remote classes using a friend member
//#ifndef TVFM_H_
//#define TVFM_H_
//
//class Tv;	// forward declaration
//
//class Remote
//{
//public:
//	enum State
//	{
//		Off, On
//	};
//	enum { MinVal, MaxVal = 20 };
//	enum { Antenna, Cable };
//	enum { TV, DVD };
//private:
//	int mode;
//public:
//	Remote(int m = TV) :mode(m) {}
//	bool volup(Tv& t);		// prototype only
//	bool voldown(Tv& t);
//	void onoff(Tv& t);
//	void chanup(Tv& t);
//	void chandown(Tv& t);
//	void set_mode(Tv& t);
//	void set_input(Tv& t);
//	void set_chan(Tv& t, int c);
//};
//
//class Tv
//{
//public:
//	friend void Remote::set_chan(Tv& t, int c);
//	enum State
//	{
//		Off, On
//	};
//	enum {MinVal, MaxVal = 20};
//	enum {Antenna, Cable};
//	enum {TV, DVD};
//
//	Tv(int s = Off, int mc = 125) :state(s), volume(5),
//		maxchannel(mc), channel(2), mode(Cable), input(TV) {}
//	void onoff() { state = (state == On) ? Off : On; }
//	bool ison() const { return state == On; }
//	bool volup();
//	bool voldown();
//	void chanup();
//	void chandown();
//	void set_mode() { mode = (mode == Antenna) ? Cable : Antenna; }
//	void set_input() { input = (input == TV) ? DVD : TV; }
//	void settings() const;
//
//private:
//	int state;
//	int volume;
//	int maxchannel;
//	int channel;
//	int mode;
//	int input;
//};
//
//// Remote methods as inline functions
//inline bool Remote::volup(Tv& t) { return t.volup(); }
//inline bool Remote::voldown(Tv& t) { return t.voldown(); }
//inline void Remote::onoff(Tv& t) { t.onoff(); }
//inline void Remote::chanup(Tv& t) { t.chanup(); }
//inline void Remote::chandown(Tv& t) { t.chandown(); }
//inline void Remote::set_mode(Tv& t) { t.set_mode(); }
//inline void Remote::set_input(Tv& t) { t.set_input(); }
//inline void Remote::set_chan(Tv& t, int c) { t.channel = c; }
//#endif // !TVFM_H_

// queuetp.h -- queue template with a nested class
//#ifndef QUEUETP_H_
//#define QUEUETP_H_
//
//template <class Item>
//class QueueTP
//{
//private:
//	enum { Q_SIZE = 10 };
//	// Node is nested class definition
//	class Node
//	{
//	public:
//		Item item;
//		Node* next;
//		Node(const Item& i) :item(i), next(0) {}
//	};
//	Node* front;	// pointer to front of Queue
//	Node* rear;		// pointer to rear of Queue
//	int items;		// current number of items in Queue
//	const int qsize;	// maximum number of items in Queue
//	QueueTP(const QueueTP& q) :qsize(0) {}
//	QueueTP& operator=(const QueueTP& q) { return *this; }
//public:
//	QueueTP(int qs = Q_SIZE);
//	~QueueTP();
//	bool isempty() const
//	{
//		return items == 0;
//	}
//	bool isfull() const
//	{
//		return items == qsize;
//	}
//	int queuecount() const
//	{
//		return items;
//	}
//	bool enqueue(const Item& item);	// add item to end
//	bool dequeue(Item& item);		// remove item from front
//};
//
//// QueueTP methods
//template <class Item>
//QueueTP<Item>::QueueTP(int qs) :qsize(qs)
//{
//	front = rear = 0;
//	items = 0;
//}
//
//template <class Item>
//QueueTP<Item>::~QueueTP()
//{
//	Node* temp;
//	while (front != 0)		// while queue is not yet empty
//	{
//		temp = front;		// save address of front item
//		front = front->next;// reset pointer to next item
//		delete temp;		// delete former front
//	}
//}
//
//// Add item to queue
//template <class Item>
//bool QueueTP<Item>::enqueue(const Item& item)
//{
//	if (isfull())
//	{
//		return false;
//	}
//	Node* add = new Node(item);		// create node
//// on failure, new throws std::bad_alloc exception
//	items++;
//	if (front == 0)			// if queue is empty, place item at front
//	{
//		front = add;
//	}
//	else
//	{
//		rear->next = add;	// else place at rear
//	}
//	rear = add;				// have rear point to new node
//	return true;
//}
//
//// Place front item into item variable and remove from queue
//template <class Item>
//bool QueueTP<Item>::dequeue(Item& item)
//{
//	if (front == 0)
//	{
//		return false;
//	}
//	item = front->item;		// set item to first item in queue
//	items--;
//	Node* temp = front;		// save location of first item
//	front = front->next;	// reset front to next item
//	delete temp;
//	if (items == 0)
//	{
//		rear = 0;
//	}
//	return true;
//}
//#endif // !QUEUETP_H_
